using Aurora.TaskScheduler.Extension;
using FileServer.Abstractions;
using FileServer.Abstractions.Models;
using FileServer.Abstractions.Models.Result;
using FileServer.Extension;
using Gateway.Common.Cache;
using Gateway.IApplication.UploadFiles.Input;
using Gateway.IApplication.UploadFiles.Output;
using Gateway.IQuery;
using Gateway.IQuery.UploadFiles.Request;
using Gateway.IQuery.UploadFiles.Result;
using Gateway.UI.Api.Filters.Attributes;
using Gateway.UI.Api.TaskJobs;
using Mapster;
using Microsoft.AspNetCore.Authorization;

namespace Gateway.UI.Api.Controllers;

/// <summary>
/// 上传文件
/// </summary>
[AllowAnonymous]
public class UploadController(
    ILogger<UploadController> logger, IFileOperator fileOperator, IRedisCache redisCache, TaskJobUtil taskJobUtil, IFileStorage fileStorage) : BaseController
{
    #region 分片上传

    /// <summary>
    /// 分片上传
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost, Microsoft.AspNetCore.Mvc.Route("files/part"), SkipLogger]
    public async Task<MultipartUploadOutput> PartUpload(PartUploadInput request)
    {
        var partSize = request.End > request.Total
               ? (request.Total - request.Start)
               : (request.End - request.Start);
        var result = new MultipartUploadOutput();
        try
        {
            var tmpData = await fileOperator.PartUploadAsync(new UploadPartInputStream
            {
                Base64 = request.Base64,
                UploadId = request.UploadId,
                PartNumber = request.PartNumber,
                PartSize = (int)partSize,
                FileName = request.FileName,
                Path = request.Path,
            });

            if (request.PartNumber < 2)
            {
                result.Path = tmpData.Path;
                result.UploadId = tmpData.UploadId;
            }
            else
            {
                result.Path = request.Path;
                result.UploadId = request.UploadId;
            }

            return result;
        }
        catch (Exception e)
        {
            logger.LogError(JsonConvert.SerializeObject(e));
        }

        return null;
    }

    /// <summary>
    /// 分片完成上传
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost, Microsoft.AspNetCore.Mvc.Route("files/part/finish")]
    public Task<string> FinishPartUpload(PartUploadFinishInput request)
    {
        taskJobUtil.InvokeLater(typeof(FinishPartUploadJob), request);
        return Task.FromResult(request.UploadId);
    }

    /// <summary>
    /// 分片完成上传的结果
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet, Route("files/part/status/{id}")]
    public Task<FinishUploadOutput> GetFinishPartUploadStatus([FromRoute] string id)
    {
        var data = redisCache.Get<FinishUploadOutput>(CacheKeys.UploadFileProgress + id);
        return Task.FromResult(data);
    }

    #endregion

    #region 普通上传

    /// <summary>
    /// 上传文件
    /// </summary>
    /// <param name="file">form 文件</param>
    /// <returns></returns>
    [HttpPost("upload"), SkipLogger]
    public async Task<FileOutput> UploadFile([FromForm] IFormFile file)
    {
        if (file == null) throw MyException.Create(404, "文件不存在");
        var data = await fileOperator.UploadAsync(new UploadFileInputForm
        {
            File = file,
            FileName = file.FileName,
            IsTemp = false,
        });
        return new FileOutput
        {
            Url = data.Url,
            Id = data.FileId,
            FileName = data.Name,
            Size = data.Length.ToString()
        };
    }

    #endregion


    /// <summary>
    /// 获取文件的分页列表
    /// </summary>
    /// <param name="request">参数</param>
    /// <returns></returns>
    [HttpPost("page/list")]
    public async Task<PageResult<UploadFilesDetailResult>> GetPageList(FilesPageListRequest request)
    {
        var data = await fileStorage.GetPageList(request.FileName, request.StartTime, request.EndTime, request.FileUrl, request.FileNo, "", request.Page, request.PageSize);
        if (data.list.Count > 0)
        {
            var t = data.list;
            List<UploadFilesDetailResult> results = new List<UploadFilesDetailResult>();
            foreach (var itemData in t)
            {
                var path = FileUploadProvider.GetDomainPath(itemData.Path);
                var item = itemData.Adapt<UploadFilesDetailResult>();
                item.UploadFilesId = itemData.Id;
                item.ExtInfo = "";
                item.Url = path;
                item.CreatedTime = itemData.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");
                item.LastModifiedTime = itemData.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");

                results.Add(item);
            }
            return PageResult<UploadFilesDetailResult>.Create(results, data.total);
        }
        return PageResult<UploadFilesDetailResult>.Create(new List<UploadFilesDetailResult>(), data.total);
    }

    /// <summary>
    /// 删除文件信息-- 文件标识
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpPost, Route("remove/{id}")]
    public async Task<bool> Remove([FromRoute] string id)
    {
        return await fileOperator.DeleteById(id);
    }

    /// <summary>
    /// 上传文件-文件流
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost, Route("upload/file"), SkipLogger]
    public async Task<UploadResult> UploadLocalFileAsync(UploadFileInputStream input)
    {
        return await fileOperator.UploadAsync(input);
    }

    /// <summary>
    /// 上传文件- fromForm
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>
    [HttpPost, Route("upload/file/fromForm"), SkipLogger]
    public async Task<UploadResult> UploadLocalFileFromFormAsync([FromForm] IFormFile file)
    {
        UploadFileInputForm input = new UploadFileInputForm();
        input.File = file;
        input.FileName = file.FileName;

        return await fileOperator.UploadAsync(input);
    }



    /// <summary>
    /// 临时文件转正式
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost, Route("temp/save"), SkipLogger]
    public async Task<bool> SaveTempAsync(string input)
    {
        return await fileOperator.SaveTemp(input);
    }

    /// <summary>
    /// 临时文件转正式-批量
    /// </summary>
    /// <param name="inputs"></param>
    /// <returns></returns>
    [HttpPost, Route("temp/save/bulk"), SkipLogger]
    public async Task<bool> SaveTempBulkAsync(List<string> inputs)
    {
        return await fileOperator.SaveTemp(inputs);
    }
}